package xyz.yuzegod.megawalls.config;

import com.google.common.base.Charsets;
import com.google.common.io.Files;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.configuration.file.YamlConstructor;
import org.bukkit.configuration.file.YamlRepresenter;
import org.bukkit.plugin.Plugin;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.BaseConstructor;
import org.yaml.snakeyaml.representer.Representer;

import java.io.*;
import java.util.logging.Logger;

public class FileConfig extends YamlConfiguration
{
    protected final DumperOptions yamlOptions;
    protected final Representer yamlRepresenter;
    protected final Yaml yaml;
    protected File file;
    protected Logger loger;
    protected Plugin plugin;
    
    public FileConfig(final Plugin plugin) {
        this(plugin, "config.yml");
    }
    
    public FileConfig(final Plugin plugin, final File file) {
        this.yamlOptions = new DumperOptions();
        this.yamlRepresenter = (Representer)new YamlRepresenter();
        this.yaml = new Yaml((BaseConstructor)new YamlConstructor(), this.yamlRepresenter, this.yamlOptions);
        Validate.notNull((Object)file, "File cannot be null");
        Validate.notNull((Object)plugin, "Plugin cannot be null");
        this.plugin = plugin;
        this.file = file;
        this.loger = plugin.getLogger();
        this.check(file);
        this.init(file);
    }
    
    public FileConfig(final Plugin plugin, final String filename) {
        this(plugin, new File(plugin.getDataFolder(), filename));
    }
    
    private void check(final File file) {
        final String filename = file.getName();
        final InputStream stream = this.plugin.getResource(filename);
        try {
            if (!file.exists()) {
                if (!file.getParentFile().exists()) {
                    file.getParentFile().mkdirs();
                }
                file.createNewFile();
                if (stream != null) {
                    this.plugin.saveResource(filename, true);
                }
            }
        }
        catch (IOException e) {
            this.loger.info("配置文件 " + filename + " 创建失败...");
        }
    }
    
    private void init(final File file) {
        Validate.notNull((Object)file, "File cannot be null");
        try {
            final FileInputStream stream = new FileInputStream(file);
            this.init(stream);
        }
        catch (FileNotFoundException e) {
            this.loger.info("配置文件 " + file.getName() + " 不存在...");
        }
    }
    
    private void init(final InputStream stream) {
        Validate.notNull((Object)stream, "Stream cannot be null");
        try {
            this.load(new InputStreamReader(stream, Charsets.UTF_8));
        }
        catch (IOException ex) {
            this.loger.info("配置文件 " + this.file.getName() + " 读取错误...");
        }
        catch (InvalidConfigurationException ex2) {
            this.loger.info("配置文件 " + this.file.getName() + " 格式错误...");
        }
    }
    
    public void setBlockLocation(final Location location, final String path) {
        final String world = location.getWorld().getName();
        final double x = location.getX();
        final double y = location.getY();
        final double z = location.getZ();
        this.set(path, (Object)(world + "," + x + "," + y + "," + z));
    }
    
    public void setLocation(final Location location, final String path) {
        final String world = location.getWorld().getName();
        final double x = location.getX();
        final double y = location.getY();
        final double z = location.getZ();
        final double yaw = location.getYaw();
        final double pitch = location.getPitch();
        this.set(path, (Object)(world + "," + x + "," + y + "," + z + "," + yaw + "," + pitch));
    }
    
    public Location getBlockLocation(final String path) {
        if (this.getString(path) != null) {
            final String locationString = this.getString(path);
            final World world = Bukkit.getWorld(locationString.split(",")[0]);
            final double x = Double.valueOf(locationString.split(",")[1]);
            final double y = Double.valueOf(locationString.split(",")[2]);
            final double z = Double.valueOf(locationString.split(",")[3]);
            return new Location(world, x, y, z);
        }
        return null;
    }
    
    public Location getLocation(final String path) {
        if (this.getString(path) != null) {
            final String locationString = this.getString(path);
            final World world = Bukkit.getWorld(locationString.split(",")[0]);
            final double x = Double.valueOf(locationString.split(",")[1]);
            final double y = Double.valueOf(locationString.split(",")[2]);
            final double z = Double.valueOf(locationString.split(",")[3]);
            final double yaw = Double.valueOf(locationString.split(",")[4]);
            final double pitch = Double.valueOf(locationString.split(",")[5]);
            return new Location(world, x, y, z, (float)yaw, (float)pitch);
        }
        return null;
    }
    
    public void load(final File file) throws IOException, InvalidConfigurationException {
        Validate.notNull((Object)file, "File cannot be null");
        final FileInputStream stream = new FileInputStream(file);
        this.load(new InputStreamReader(stream, Charsets.UTF_8));
    }
    
    public void load(final Reader reader) throws IOException, InvalidConfigurationException {
        final BufferedReader input = (BufferedReader)((reader instanceof BufferedReader) ? reader : new BufferedReader(reader));
        final StringBuilder builder = new StringBuilder();
        try {
            String line;
            while ((line = input.readLine()) != null) {
                builder.append(line);
                builder.append('\n');
            }
        }
        finally {
            input.close();
        }
        this.loadFromString(builder.toString());
    }
    
    public void reload() {
        this.init(this.file);
    }
    
    public void save() {
        if (this.file == null) {
            this.loger.info("未定义配置文件路径 保存失败!");
        }
        try {
            this.save(this.file);
        }
        catch (IOException e) {
            this.loger.info("配置文件 " + this.file.getName() + " 保存错误...");
            e.printStackTrace();
        }
    }
    
    public void save(final File file) throws IOException {
        Validate.notNull((Object)file, "File cannot be null");
        Files.createParentDirs(file);
        final String data = this.saveToString();
        final Writer writer = new OutputStreamWriter(new FileOutputStream(file), Charsets.UTF_8);
        try {
            writer.write(data);
        }
        finally {
            writer.close();
        }
    }
    
    public String saveToString() {
        this.yamlOptions.setIndent(this.options().indent());
        this.yamlOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
        this.yamlRepresenter.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
        final String header = this.buildHeader();
        String dump = this.yaml.dump((Object)this.getValues(false));
        if (dump.equals("{}\n")) {
            dump = "";
        }
        return header + dump;
    }
}
